package com.cq.hd.member.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cq.hd.common.enums.biz.WithdrawalCheckItemTypeEnum;
import com.cq.hd.common.enums.biz.WithdrawalCheckTypeEnum;
import com.cq.hd.common.exception.BusinessException;
import com.cq.hd.common.response.Result;
import com.cq.hd.common.response.Throw;
import com.cq.hd.common.utils.BeanUtils;
import com.cq.hd.member.api.dto.CheckFileExcelParamDto;
import com.cq.hd.member.api.dto.WithdrawalCheckBillSaveDto;
import com.cq.hd.member.api.vo.*;
import com.cq.hd.member.mapper.TbWithdrawalCheckBillMapper;
import com.cq.hd.member.mapper.TbWithdrawalCheckItemMapper;
import com.cq.hd.member.po.TbWithdrawalBillPo;
import com.cq.hd.member.po.TbWithdrawalCheckBillPo;
import com.cq.hd.member.po.TbWithdrawalCheckItemPo;
import com.cq.hd.member.service.TbMerchantService;
import com.cq.hd.member.service.TbWithdrawalCheckBillService;
import com.cq.hd.order.api.TbMonthSettleBillWithdrawalApi;
import com.cq.hd.order.api.vo.MonthSettleBillVo;
import com.cq.hd.system.api.OssApi;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author much
 * @since 2024/04/18 22:44
 */
@Slf4j
@Service
public class TbWithdrawalCheckBillServiceImpl extends ServiceImpl<TbWithdrawalCheckBillMapper, TbWithdrawalCheckBillPo>
        implements TbWithdrawalCheckBillService {

    @Resource
    private TbWithdrawalCheckBillMapper withdrawalCheckBillMapper;
    @Resource
    private TbWithdrawalCheckItemMapper withdrawalCheckItemMapper;
    @Resource
    private TbMerchantService merchantService;
    @Resource
    private TbMonthSettleBillWithdrawalApi monthSettleBillWithdrawalApi;
    @Resource
    private PlatformTransactionManager transactionManager;
    @Resource
    private OssApi ossApi;

    @Value("${hd.check-file.local-path}")
    private String checkFileLocalPath;
    @Value("${hd.check-file.amt-template:}")
    private String checkFileAmtTemplatePath;
    @Value("${hd.check-file.subsidy-template:}")
    private String checkFileSubsidyTemplatePath;

    /**
     * 核算单列表
     *
     * @param withdrawalBillIds 提现记录ids
     * @return 核算单列表
     */
    @Override
    public List<WithdrawalCheckBillVo> listByWithdrawalBillIds(Collection<Long> withdrawalBillIds) {
        if (CollectionUtils.isEmpty(withdrawalBillIds)) {
            return Collections.emptyList();
        }
        LambdaQueryWrapper<TbWithdrawalCheckBillPo> qw = Wrappers.<TbWithdrawalCheckBillPo>lambdaQuery()
                .in(TbWithdrawalCheckBillPo::getWithdrawalBillId, withdrawalBillIds);
        List<TbWithdrawalCheckBillPo> tbWithdrawalCheckBills = withdrawalCheckBillMapper.selectList(qw);
        return BeanUtils.copyListProperties(tbWithdrawalCheckBills, WithdrawalCheckBillVo::new);
    }

    /**
     * 核算单详情
     *
     * @param id 核算单id
     * @return 核算单详情
     */
    @Override
    public WithdrawalCheckBillVo getDetail(Long id) {
        TbWithdrawalCheckBillPo withdrawalCheckBillPo = Optional.ofNullable(withdrawalCheckBillMapper.selectById(id))
                .orElseThrow(() -> new BusinessException("核算单不存在"));
        WithdrawalCheckBillVo withdrawalCheckBillVo = BeanUtil.copyProperties(withdrawalCheckBillPo, WithdrawalCheckBillVo.class);
        withdrawalCheckBillVo.setItems(listItems(id));
        return withdrawalCheckBillVo;
    }

    /**
     * 核算单确认
     *
     * @param id 核算单id
     * @return 操作结果
     */
    @Override
    public Boolean confirm(Long id) {
        return withdrawalCheckBillMapper.confirm(id) == 1;
    }

    /**
     * 初始化核算单
     *
     * @param withdrawalBillPo 提现记录
     */
    @Override
    public WithdrawalCheckBillInitVo initializeCheckBill(TbWithdrawalBillPo withdrawalBillPo) {
        TbWithdrawalCheckBillPo withdrawalCheckBillPo = withdrawalCheckBillMapper.selectByWithdrawalBillId(withdrawalBillPo.getId());
        if (withdrawalCheckBillPo != null) {
            return getInitVoWithExistCheckBill(withdrawalCheckBillPo);
        } else {
            return doInitializeCheckBill(withdrawalBillPo);
        }
    }

    @Override
    public WithdrawalCheckBillInitVo checkInfo(Long checkBillId) {
        TbWithdrawalCheckBillPo withdrawalCheckBillPo = withdrawalCheckBillMapper.selectById(checkBillId);
        if (withdrawalCheckBillPo != null) {
            return getInitVoWithExistCheckBill(withdrawalCheckBillPo);
        }
        throw new BusinessException("核算单不存在");
    }

    @Transactional
    @Override
    public CheckBillSaveResultVo saveCheckBill(WithdrawalCheckBillSaveDto checkBillSaveDto) {
        TbWithdrawalCheckBillPo withdrawalCheckBillPo = withdrawalCheckBillMapper.selectById(checkBillSaveDto.getCheckBillId());
        if (withdrawalCheckBillPo == null) {
            Throw.isBusinessException("核算单还未初始化");
        }
        saveCheckItems(checkBillSaveDto);

        withdrawalCheckBillPo.setStatus(1);
        withdrawalCheckBillPo.setUpdateTime(LocalDateTime.now());
        // 更新finalAmt
        List<TbWithdrawalCheckItemPo> checkItems = withdrawalCheckItemMapper.selectByCheckBillId(checkBillSaveDto.getCheckBillId());
        withdrawalCheckBillPo.setFinalAmt(calculateFinalAmt(withdrawalCheckBillPo.getWithdrawalAmt(), checkItems));
        // 统计手续费和扣款总额
        CheckBillSaveResultVo checkBillSaveResultVo = new CheckBillSaveResultVo();
        checkBillSaveResultVo.setFeeAmt(checkItems.stream()
                .filter(e -> WithdrawalCheckItemTypeEnum.FEE.getValue() == e.getType())
                .map(TbWithdrawalCheckItemPo::getItemAmt)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        checkBillSaveResultVo.setCheckDeductAmt(getCheckDeductAmt(checkItems));
        // 生成结算单文件
        generateCheckFile(withdrawalCheckBillPo, checkItems);
        updateById(withdrawalCheckBillPo);

        return checkBillSaveResultVo;
    }

    private BigDecimal getCheckDeductAmt(List<TbWithdrawalCheckItemPo> checkItems) {
        if (CollectionUtils.isEmpty(checkItems)) {
            return BigDecimal.ZERO;
        }
        BigDecimal result = BigDecimal.ZERO;
        for (TbWithdrawalCheckItemPo item : checkItems) {
            if (item.getType() == WithdrawalCheckItemTypeEnum.DEDUCTION.getValue()) {
                result = result.add(item.getItemAmt());
            } else if (item.getType() == WithdrawalCheckItemTypeEnum.ADD.getValue()) {
                result = result.subtract(item.getItemAmt());
            }
        }
        return result;
    }

    private void generateCheckFile(TbWithdrawalCheckBillPo checkBill, List<TbWithdrawalCheckItemPo> checkItems) {
        CheckFileExcelParamDto checkFileExcelParamDto = null;
        if (WithdrawalCheckTypeEnum.MERCHANT_AMT.getValue() == checkBill.getCheckType()) {
            checkFileExcelParamDto = getCheckFileExcelParam4MerchantAmt(checkBill, checkItems);
        } else {
            checkFileExcelParamDto = getCheckFileExcelParam4SubsidyAmt(checkBill, checkItems);
        }

        // 上传至OSS
        InputStream inputStream = null;
        try {
            URL url = new URL(checkFileExcelParamDto.getTemplateFilePath());
            // 打开连接并获取输入流
            inputStream = url.openStream();

            File file = new File(checkFileExcelParamDto.getTargetFilePath());
            // 获取文件所在的目录路径
            String directoryPath = file.getParent();
            File directory = new File(directoryPath);
            if (!directory.exists()) {
                directory.mkdirs();
            }
            try (ExcelWriter excelWriter = EasyExcel.write(file)
                    .withTemplate(inputStream).build()) {
                WriteSheet writeSheet = EasyExcel.writerSheet().build();
                FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
                excelWriter.fill(checkFileExcelParamDto.getFormData(), fillConfig, writeSheet);
                excelWriter.fill(checkFileExcelParamDto.getListData(), fillConfig, writeSheet);
            }

            File localFile = new File(checkFileExcelParamDto.getTargetFilePath());
            FileInputStream fileInputStream = new FileInputStream(localFile);

            // 创建 StandardMultipartFile 对象
            MultipartFile multipartFile = new MockMultipartFile(localFile.getName(), localFile.getName(), null, fileInputStream);
            Result<String> uploadResult = ossApi.uploadFile(multipartFile, "checkBill", localFile.getName());
            if (uploadResult.getCode() == 200) {
                checkBill.setCheckFile(uploadResult.getData());
            } else {
                Throw.isBusinessException("上传核算单出错");
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    private CheckFileExcelParamDto getCheckFileExcelParam4MerchantAmt(TbWithdrawalCheckBillPo checkBill, List<TbWithdrawalCheckItemPo> checkItems) {
        CheckFileExcelParamDto checkFileExcelParamDto = new CheckFileExcelParamDto();
        checkFileExcelParamDto.setTemplateFilePath(checkFileAmtTemplatePath);
        String targetFilePath = checkFileLocalPath + "本金核算单_" + checkBill.getCreateTime().toLocalDate() + "_" + System.currentTimeMillis() + ".xlsx";
        checkFileExcelParamDto.setTargetFilePath(targetFilePath);
        // 主表单数据
        Map<String, String> formData = new HashMap<>();
        formData.put("partA", checkBill.getPartA());
        formData.put("partB", checkBill.getPartB());
        formData.put("serviceItemDesc", checkBill.getServiceItemDesc());
        formData.put("collaborateModeText", "代理发放");
        formData.put("withdrawalAmt", checkBill.getWithdrawalAmt().toString());
        formData.put("finalAmt", checkBill.getFinalAmt().toString());
        checkFileExcelParamDto.setFormData(formData);
        // 列表数据
        List<Map<String, String>> listData = checkItems.stream()
                .filter(e -> WithdrawalCheckItemTypeEnum.MERCHANT_AMT.getValue() != e.getType())
                .map(e -> {
                    Map<String, String> item = new HashMap<>();
                    item.put("itemName", e.getItemDesc());
                    item.put("itemNumber", e.getItemAmt().toString());
                    return item;
                })
                .collect(Collectors.toList());
        checkFileExcelParamDto.setListData(listData);

        return checkFileExcelParamDto;
    }

    private CheckFileExcelParamDto getCheckFileExcelParam4SubsidyAmt(TbWithdrawalCheckBillPo checkBill, List<TbWithdrawalCheckItemPo> checkItems) {
        CheckFileExcelParamDto checkFileExcelParamDto = new CheckFileExcelParamDto();
        checkFileExcelParamDto.setTemplateFilePath(checkFileSubsidyTemplatePath);
        String targetFilePath = checkFileLocalPath + "补贴核算单_" + checkBill.getCreateTime().toLocalDate() + "_" + System.currentTimeMillis() + ".xlsx";
        checkFileExcelParamDto.setTargetFilePath(targetFilePath);
        // 主表单数据
        Map<String, String> formData = new HashMap<>();
        formData.put("partB", checkBill.getPartB());
        formData.put("partA", checkBill.getPartA());
        formData.put("serviceItemDesc", checkBill.getServiceItemDesc());
        formData.put("collaborateModeText", "代理发放");
        formData.put("finalAmt", checkBill.getFinalAmt().toString());
        checkFileExcelParamDto.setFormData(formData);
        // 列表数据
        List<Map<String, String>> settleItems = checkItems.stream()
                .filter(e -> WithdrawalCheckItemTypeEnum.MERCHANT_SUBSIDY.getValue() == e.getType())
                .map(e -> {
                    Map<String, String> item = new HashMap<>();
                    item.put("settleItem", e.getItemDesc());
                    item.put("settleAmt", e.getItemAmt().toString());
                    return item;
                }).collect(Collectors.toList());
        List<Map<String, String>> otherItems = checkItems.stream()
                .filter(e -> WithdrawalCheckItemTypeEnum.MERCHANT_SUBSIDY.getValue() != e.getType())
                .map(e -> {
                    Map<String, String> item = new HashMap<>();
                    item.put("itemName", e.getItemDesc());
                    item.put("itemNumber", e.getItemAmt().toString());
                    return item;
                }).collect(Collectors.toList());
        // 合并两个列表
        List<Map<String, String>> mainList = (settleItems.size() >= otherItems.size()) ? settleItems : otherItems;
        List<Map<String, String>> secondaryList = (mainList == settleItems) ? otherItems : settleItems;

        // 遍历主 List，将对应位置的 Map 合并
        for (int i = 0; i < mainList.size(); i++) {
            Map<String, String> mainMap = mainList.get(i);
            Map<String, String> secondaryMap = (i < secondaryList.size()) ? secondaryList.get(i) : null;
            if (secondaryMap != null) {
                mainMap.putAll(secondaryMap);
            }
        }
        checkFileExcelParamDto.setListData(mainList);

        return checkFileExcelParamDto;
    }

    private BigDecimal calculateFinalAmt(BigDecimal withdrawalAmt, List<TbWithdrawalCheckItemPo> items) {
        BigDecimal finalAmt = withdrawalAmt;
        for (TbWithdrawalCheckItemPo item : items) {
            if (WithdrawalCheckItemTypeEnum.DEDUCTION.getValue() == item.getType()
                    || WithdrawalCheckItemTypeEnum.FEE.getValue() == item.getType()) {
                finalAmt = finalAmt.subtract(item.getItemAmt());
            } else if (WithdrawalCheckItemTypeEnum.ADD.getValue() == item.getType()) {
                finalAmt = finalAmt.add(item.getItemAmt());
            }
        }
        return finalAmt;
    }

    @Override
    public WithdrawalCheckBillPreVo preCheckBill(Long checkBillId) {
        TbWithdrawalCheckBillPo checkBill = withdrawalCheckBillMapper.selectById(checkBillId);
        WithdrawalCheckBillPreVo checkBillPreVo = BeanUtil.copyProperties(checkBill, WithdrawalCheckBillPreVo.class);

        List<TbWithdrawalCheckItemPo> checkItems = withdrawalCheckItemMapper.selectByCheckBillId(checkBillId);
        // 过滤掉本金账单展示
//        List<TbWithdrawalCheckItemPo> items = checkItems.stream().filter(item -> item.getType() != WithdrawalCheckItemTypeEnum.MERCHANT_SUBSIDY.getValue())
//                .collect(Collectors.toList());
        checkBillPreVo.setItems(BeanUtils.copyListProperties(checkItems, WithdrawalCheckItemVo::new));

        return checkBillPreVo;
    }

    private void saveCheckItems(WithdrawalCheckBillSaveDto checkBillSaveDto) {
        List<WithdrawalCheckBillSaveDto.CheckItem> newItems = checkBillSaveDto.getItems().stream()
                .filter(e -> WithdrawalCheckItemTypeEnum.DEDUCTION.getValue() == e.getType()
                        || WithdrawalCheckItemTypeEnum.ADD.getValue() == e.getType())
                .collect(Collectors.toList());
        // 先删除原来type in (4-手动扣款 5-手动增加)的类型
        withdrawalCheckItemMapper.deleteByCheckBillId(
                checkBillSaveDto.getCheckBillId(),
                Arrays.asList(WithdrawalCheckItemTypeEnum.DEDUCTION.getValue(), WithdrawalCheckItemTypeEnum.ADD.getValue()));
        newItems.forEach(item -> {
                    TbWithdrawalCheckItemPo checkItemPo = BeanUtil.copyProperties(item, TbWithdrawalCheckItemPo.class);
                    checkItemPo.setCheckBillId(checkBillSaveDto.getCheckBillId());
                    checkItemPo.setCreateTime(LocalDateTime.now());
                    withdrawalCheckItemMapper.insert(checkItemPo);
                });

    }

    private List<WithdrawalCheckItemVo> listItems(Long id) {
        LambdaQueryWrapper<TbWithdrawalCheckItemPo> eq = Wrappers.<TbWithdrawalCheckItemPo>lambdaQuery()
                .eq(TbWithdrawalCheckItemPo::getCheckBillId, id);
        List<TbWithdrawalCheckItemPo> tbWithdrawalCheckItems = withdrawalCheckItemMapper.selectList(eq);
        if (CollectionUtils.isEmpty(tbWithdrawalCheckItems)) {
            return Collections.emptyList();
        }
        return BeanUtils.copyListProperties(tbWithdrawalCheckItems, WithdrawalCheckItemVo::new);
    }

    private WithdrawalCheckBillInitVo getInitVoWithExistCheckBill(TbWithdrawalCheckBillPo withdrawalCheckBillPo) {
        List<TbWithdrawalCheckItemPo> checkItems = withdrawalCheckItemMapper.selectByCheckBillId(withdrawalCheckBillPo.getId());
        return getInitVo(withdrawalCheckBillPo, checkItems);
    }

    private WithdrawalCheckBillInitVo doInitializeCheckBill(TbWithdrawalBillPo withdrawalBillPo) {
        TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());
        try {
            TbWithdrawalCheckBillPo checkBill = createCheckBill(withdrawalBillPo);
            // items
            List<TbWithdrawalCheckItemPo> checkItems = createCheckItems(checkBill);
            // 更新finalAmt
            BigDecimal totalFeeAmt = checkItems.stream().filter(e -> WithdrawalCheckItemTypeEnum.FEE.getValue() == e.getType())
                    .map(TbWithdrawalCheckItemPo::getItemAmt)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            checkBill.setFinalAmt(checkBill.getWithdrawalAmt().subtract(totalFeeAmt));
            updateById(checkBill);
            transactionManager.commit(transaction);
            return getInitVo(checkBill, checkItems);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            transactionManager.rollback(transaction);
            Throw.isBusinessException(e.getMessage());
        }
        return null;
    }

    private WithdrawalCheckBillInitVo getInitVo(TbWithdrawalCheckBillPo checkBill, List<TbWithdrawalCheckItemPo> checkItems) {
        WithdrawalCheckBillInitVo initVo = BeanUtil.copyProperties(checkBill, WithdrawalCheckBillInitVo.class);
        // 过滤掉本金账单展示
        List<TbWithdrawalCheckItemPo> items = checkItems.stream().filter(item -> item.getType() != WithdrawalCheckItemTypeEnum.MERCHANT_AMT.getValue())
                .collect(Collectors.toList());
        initVo.setItems(BeanUtils.copyListProperties(items, WithdrawalCheckItemVo::new));
        return initVo;
    }

    private TbWithdrawalCheckBillPo createCheckBill(TbWithdrawalBillPo withdrawalBillPo) {
        TbWithdrawalCheckBillPo checkBillPo = new TbWithdrawalCheckBillPo();
        checkBillPo.setWithdrawalBillId(withdrawalBillPo.getId());
        checkBillPo.setPartA("厦门火动通告科技有限公司");
        MerchantVo merchantVo = merchantService.getMerchantById(withdrawalBillPo.getWithdrawalUserId());
        checkBillPo.setPartB(merchantVo.getMerchantName());
        checkBillPo.setMerchantId(merchantVo.getId());
        checkBillPo.setSettleModel(2); //不定期结算
        checkBillPo.setCollaborateMode(1); // 代发
        checkBillPo.setWithdrawalAmt(withdrawalBillPo.getTradeAmt());
        checkBillPo.setFinalAmt(withdrawalBillPo.getTradeAmt());
        checkBillPo.setCheckType(withdrawalBillPo.getWithdrawalType());
        checkBillPo.setStatus(0); // 状态：0-初始化 1-待确认 2-已确认
        WithdrawalCheckTypeEnum withdrawalCheckType = WithdrawalCheckTypeEnum.valueOfWithdrawalType(withdrawalBillPo.getWithdrawalType());
        checkBillPo.setCheckType(withdrawalCheckType.getValue());
        checkBillPo.setServiceItemDesc(withdrawalCheckType.getText());
        checkBillPo.setCreateTime(LocalDateTime.now());
        withdrawalCheckBillMapper.insert(checkBillPo);
        return checkBillPo;
    }

    private List<TbWithdrawalCheckItemPo> createCheckItems(TbWithdrawalCheckBillPo checkBillPo) {
        // 根据提现单查询对应的月度账单
        List<MonthSettleBillVo> monthSettleBillVos = monthSettleBillWithdrawalApi.listByWithdrawalId(checkBillPo.getWithdrawalBillId()).unpack();
        if (CollectionUtils.isEmpty(monthSettleBillVos)) {
            Throw.isBusinessException("此提现无需核算");
            log.error("[提现核算] - 查询月度账单为空");
        }
        List<TbWithdrawalCheckItemPo> items = new ArrayList<>();
        // 生成账单明细
        if (WithdrawalCheckTypeEnum.MERCHANT_AMT.getValue() == checkBillPo.getCheckType()) {
            items.addAll(getMerchantAmtCheckItems(checkBillPo.getId(), monthSettleBillVos));
        } else {
            items.addAll(getSubsidyAmtCheckItems(checkBillPo.getId(), monthSettleBillVos));
        }
        // 生成手续费明细
        items.addAll(getFeeAmtCheckItems(items));
        // 批量保存
        for (TbWithdrawalCheckItemPo item : items) {
            withdrawalCheckItemMapper.insert(item);
        }

        return items;
    }

    private List<TbWithdrawalCheckItemPo> getMerchantAmtCheckItems(Long checkBillId, List<MonthSettleBillVo> monthSettleBillVos) {
        BigDecimal totalAmt = monthSettleBillVos.stream().map(MonthSettleBillVo::getTradeAmt)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        TbWithdrawalCheckItemPo checkItemPo = buildCheckItemPo(
                checkBillId, totalAmt, "本金账单金额", WithdrawalCheckItemTypeEnum.MERCHANT_AMT.getValue(), null);
        return Collections.singletonList(checkItemPo);
    }

    private List<TbWithdrawalCheckItemPo> getSubsidyAmtCheckItems(Long checkBillId, List<MonthSettleBillVo> monthSettleBillVos) {
        return monthSettleBillVos.stream()
                .map(e -> buildCheckItemPo(
                        checkBillId, e.getTradeAmt(), e.getSettleDate(), WithdrawalCheckItemTypeEnum.MERCHANT_SUBSIDY.getValue(), e.getId()))
                .collect(Collectors.toList());
    }

    private List<TbWithdrawalCheckItemPo> getFeeAmtCheckItems(List<TbWithdrawalCheckItemPo> items) {
        List<Integer> needFeeTypes = Arrays.asList(WithdrawalCheckItemTypeEnum.MERCHANT_AMT.getValue(), WithdrawalCheckTypeEnum.MERCHANT_SUBSIDY.getValue());
        List<TbWithdrawalCheckItemPo> needGenerateFeeItems = items.stream().filter(e -> needFeeTypes.contains(e.getType()))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(needGenerateFeeItems)) {
            return Collections.emptyList();
        }
        return needGenerateFeeItems.stream().map(this::buildFeeAmtCheckItemPo).collect(Collectors.toList());
    }

    private TbWithdrawalCheckItemPo buildFeeAmtCheckItemPo(TbWithdrawalCheckItemPo withdrawalCheckItemPo) {
        TbWithdrawalCheckItemPo checkItemPo = BeanUtil.copyProperties(withdrawalCheckItemPo, TbWithdrawalCheckItemPo.class);
        BigDecimal feeAmt = NumberUtil.mul(withdrawalCheckItemPo.getItemAmt(), new BigDecimal("0.005"));
        BigDecimal minFeeAmt = new BigDecimal("0.01");
        if (feeAmt.compareTo(minFeeAmt) < 0) {
            feeAmt = minFeeAmt;
        }
        checkItemPo.setItemAmt(feeAmt.setScale(2, RoundingMode.HALF_UP));
        checkItemPo.setItemDesc(checkItemPo.getItemDesc() + "手续费");
        checkItemPo.setType(WithdrawalCheckItemTypeEnum.FEE.getValue());
        return checkItemPo;
    }

    private TbWithdrawalCheckItemPo buildCheckItemPo(Long checkBillId, BigDecimal amt, String desc, int type, Long monthSettleBillId) {
        TbWithdrawalCheckItemPo checkItemPo = new TbWithdrawalCheckItemPo();
        checkItemPo.setCheckBillId(checkBillId);
        checkItemPo.setItemAmt(amt);
        checkItemPo.setItemDesc(desc);
        checkItemPo.setType(type);
        checkItemPo.setMonthSettleId(monthSettleBillId);
        checkItemPo.setCreateTime(LocalDateTime.now());
        return checkItemPo;
    }

}
